package linear.linked.single.circle;

import java.util.Iterator;

/**
 * 单向循环链表
 * @author caasi
 * @since 2022年1月18日09:27:59
 */
public class SingleCircularLinkedList<E> implements Iterable<E> {

    //头结点，指向第一个元素
    private Node<E> first;

    //链表长度
    private int size;

    //构造方法
    public SingleCircularLinkedList() {
        this.size = 0;
        this.first = null;
    }

    //清空链表
    public void clear() {
        first = null;
        size = 0;
    }

    //判断链表是否为空
    public boolean isEmpty() {
        return size == 0;
    }

    //链表的长度
    public int size() {
        return size;
    }

    //返回下标为i的元素
    public E get(int index) {
        checkIndexSafe(index);
        Node<E> node = node(index);
        return node.value;
    }

    //向链表添加元素
    public void insert(E t) {
        Node<E> newNode = new Node<>(t, first);
        if (first == null) {
            first = newNode;
            newNode.next = newNode;
        } else {
            Node<E> before = node(size - 1);
            before.next = newNode;
        }
        size++;
    }

    //向链表下标为i的元素之前添加元素
    public void insert(E t, int index) {
        checkIndexSafe(index);
        Node<E> before = node(index - 1);
        Node<E> next = before.next;
        Node<E> newNode = new Node<>(t, next);
        before.next = newNode;
        size++;
    }

    //删除下标为i的元素并返回
    public E remove(int index) {
        checkIndexSafe(index);
        //找到下标为i的节点前面的一个节点
        Node<E> node = node(index - 1);
        Node<E> remove = node.next;
        if (remove == node)
            first = null;
        else {
            if (remove == first)
                first = remove.next;
            node.next = remove.next;
        }
        size--;
        return remove.value;
    }

    //返回链表中首次出现的元素t的下标，如果没有t元素，则返回-1
    public int indexOf(E t) {
        if (isEmpty())
            return -1;
        Node<E> node = first;
        int index = 0;
        for (; index < size; index++) {
            if (node.value.equals(t))
                return index;
            node = node.next;
        }
        return -1;
    }

    //约瑟夫问题
    public void josephQuestion(int count) {
        int index = 1;
        Node<E> start = first;
        Node<E> removeBefore = null;
        while (true) {
            //只剩一个人退出
            if (start.next == start) {
                System.out.println("最后幸存下来的人的编号为：" + start.value);
                break;
            }
            //报数
            for (int i = 0; i < count - 1; i++) {
                removeBefore = start;
                start = start.next;
            }
            //当前start代表的人自杀
            removeBefore.next = start.next;
            System.out.println("第" + index + "次自杀的人的编号为：" + start.value);
            //start后移一个人准备下一轮
            start = start.next;
            index++;
        }
    }

    //查找下标为i的节点
    private Node<E> node(int index) {
        if (index < 0)
            index = size - Math.abs(index);
        Node<E> node = first;
        for (int i = 0; i < index; i++)
            node = node.next;
        return node;
    }

    //检查下标是否安全
    private void checkIndexSafe(int index) {
        if (index < 0 || index >= size)
            throw new IndexOutOfBoundsException();
    }

    //迭代器
    @Override
    public Iterator<E> iterator() {
        return new SingleCircularLinkedListIterator();
    }

    //迭代器内部类
    private class SingleCircularLinkedListIterator implements Iterator<E> {

        private Node<E> current;
        
        private int cursor;

        public SingleCircularLinkedListIterator() {
            this.current = first;
            this.cursor = 0;
        }

        @Override
        public boolean hasNext() {
            return current != null && cursor != size;
        }

        @Override
        public E next() {
            E val = current.value;
            current = current.next;
            cursor++;
            return val;
        }
    }

    //节点内部类
    private class Node<E> {

        //值域
        private E value;

        //指针域
        private Node<E> next;

        //构造方法
        public Node(E value, Node<E> next) {
            this.value = value;
            this.next = next;
        }

    }

}
